<template>
  <el-container style="height: 100vh;">
    <el-header>
      <h1>新建小说与内容处理</h1>
    </el-header>
    <el-main>
      <el-form ref="form" :model="form" label-width="80px">
        <el-form-item label="书名" :required="true">
          <el-input v-model="form.bookName"></el-input>
        </el-form-item>
        <el-form-item label="分类" :required="true">
          <el-select v-model="form.kindIds" placeholder="请选择分类" multiple>
            <el-option label="科幻" value="科幻"></el-option>
            <el-option label="奇幻" value="奇幻"></el-option>
            <el-option label="修仙" value="修仙"></el-option>
            <el-option label="穿越" value="穿越"></el-option>
            <el-option label="爱情" value="爱情"></el-option>
            <el-option label="侦探" value="侦探"></el-option>
            <el-option label="冒险" value="冒险"></el-option>
          </el-select>
        </el-form-item>
        <el-form-item label="章节标题" :required="true">
          <el-input v-model="form.chapName"></el-input>
        </el-form-item>
        <el-form-item>
          <el-button type="primary" :disabled="!isFormValid" @click="showUploadButton = true" style="width: 100%;">确认信息</el-button>
        </el-form-item>
      </el-form>
      <el-dialog title="上传文件" :visible.sync="uploadVisible" v-if="showUploadButton">
        <el-upload
          class="upload-demo"
          drag
          action=""
          :auto-upload="false"
          :on-change="handleFileUpload"
          accept=".pdf,.docx,.txt">
          <i class="el-icon-upload"></i>
          <div class="el-upload__text">拖拽文件到这里，或<em>点击上传</em></div>
          <div class="el-upload__tip" slot="tip">只能上传 PDF、Word 或 TXT 文件</div>
        </el-upload>
        <span slot="footer" class="dialog-footer">
          <el-button @click="uploadVisible = false">取 消</el-button>
        </span>
      </el-dialog>
      <div class="floating-upload" v-if="showUploadButton">
        <el-button type="primary" icon="el-icon-upload" @click="uploadVisible = true" style="width: 100%;">上传文件</el-button>
      </div>
      <el-row :gutter="20" v-if="processedContent">
        <el-col :span="24">
          <el-card>
            <h2>{{ form.bookName }}</h2>
            <h3>{{ form.chapName }}</h3>
            <el-scrollbar style="max-height: 400px;">
              <el-input type="textarea" v-model="processedContent" class="pre-wrap" :rows="10"></el-input>
            </el-scrollbar>
            <el-button type="primary" @click="submitProcessedContent">提交</el-button>
            <el-button type="primary" @click="downloadProcessedFile">下载处理后的文件</el-button>
          </el-card>
        </el-col>
      </el-row>
      <el-message-box :title="messageBoxTitle" :visible.sync="messageBoxVisible" type="success">
        <span>{{ messageBoxContent }}</span>
      </el-message-box>
    </el-main>
  </el-container>
</template>

<script>
import axios from 'axios';
import * as pdfjsLib from 'pdfjs-dist/build/pdf';
import PizZip from 'pizzip';
import Docxtemplater from 'docxtemplater';
import { v4 as uuidv4 } from 'uuid';

export default {
  data() {
    return {
      form: {
        bookName: '',
        kindIds: [],
        chapName: '',
        content: ''
      },
      formattedText: '',
      selectedFile: null,
      sessionId: uuidv4(),
      matchedKeywords: [],
      keywords: [],
      explanations: {},
      backendResponse: '',
      processedContent: '',
      uploadVisible: false,
      showUploadButton: false,
      messageBoxVisible: false,
      messageBoxTitle: '',
      messageBoxContent: ''
    };
  },
  computed: {
    isFormValid() {
      return this.form.bookName && this.form.kindIds.length > 0 && this.form.chapName;
    }
  },
  created() {
    this.fetchVocabulary();
  },
  methods: {
    fetchVocabulary() {
      axios.get('/api/vocabulary')
        .then(response => {
          this.keywords = response.data.map(v => v.word);
          this.explanations = response.data.reduce((acc, v) => {
            acc[v.word] = v.explanation;
            return acc;
          }, {});
        })
        .catch(error => {
          console.error('Error fetching vocabulary:', error);
        });
    },
    extractSentencesWithKeywords(text) {
      const sentences = text.split(/(?<=[。！？])/);
      const matchedSentences = sentences.filter(sentence => {
        const matched = this.keywords.some(keyword => sentence.includes(keyword));
        if (matched) {
          this.matchedKeywords = [...new Set([...this.matchedKeywords, ...this.keywords.filter(keyword => sentence.includes(keyword))])];
        }
        return matched;
      });
      return matchedSentences.map((sentence, index) => `${index + 1}. ${sentence}`).join(' ');
    },
    async handleFileUpload(file) {
      if (file) {
        this.selectedFile = file.raw;
        const fileType = file.raw.type;
        if (fileType === 'application/pdf') {
          await this.extractTextFromPDF(file.raw);
        } else if (fileType === 'application/vnd.openxmlformats-officedocument.wordprocessingml.document') {
          await this.extractTextFromWord(file.raw);
        } else if (fileType === 'text/plain') {
          await this.extractTextFromTxt(file.raw);
        }
        this.sendToBackend();
      }
    },
    async extractTextFromPDF(file) {
      const reader = new FileReader();
      reader.onload = async (e) => {
        const typedArray = new Uint8Array(e.target.result);
        const pdf = await pdfjsLib.getDocument(typedArray).promise;
        let text = '';
        for (let pageNum = 1; pageNum <= pdf.numPages; pageNum++) {
          const page = await pdf.getPage(pageNum);
          const textContent = await page.getTextContent();
          textContent.items.forEach(item => {
            text += item.str + ' ';
          });
        }
        this.formattedText = this.extractSentencesWithKeywords(text);
        this.sendToBackend();
      };
      reader.readAsArrayBuffer(file);
    },
    async extractTextFromWord(file) {
      const reader = new FileReader();
      reader.onload = async (e) => {
        const content = e.target.result;
        const zip = new PizZip(content);
        const doc = new Docxtemplater(zip, {
          paragraphLoop: true,
          linebreaks: true,
        });
        const text = doc.getFullText();
        this.formattedText = this.extractSentencesWithKeywords(text);
        this.sendToBackend();
      };
      reader.readAsBinaryString(file);
    },
    async extractTextFromTxt(file) {
      const reader = new FileReader();
      reader.onload = async (e) => {
        const text = e.target.result;
        this.formattedText = this.extractSentencesWithKeywords(text);
        this.sendToBackend();
      };
      reader.readAsText(file);
    },
    async sendToBackend() {
      const matchedKeywordsStr = this.matchedKeywords.join(', ');
      let contentToSend = `现在对以下词语进行定义：\n`;
      let counter = 1;
      this.matchedKeywords.forEach(keyword => {
        const explanation = this.explanations[keyword];
        contentToSend += `${counter}.${keyword}：${explanation}\n`;
        counter++;
      });
      let highlightedText = this.formattedText;
      this.matchedKeywords.forEach(keyword => {
        const regex = new RegExp(`(${keyword})`, 'g');
        highlightedText = highlightedText.replace(regex, '“$1”');
      });
      contentToSend += `请判断下列每个句子中${matchedKeywordsStr}的意思并与上述定义比较，意思相同返回编号-1（如1-1、5-1），不同则返回编号-0： ${highlightedText}`;
      const requestBody = { content: contentToSend, sessionId: this.sessionId };
      try {
        const response = await axios.post('/api/content/send', requestBody);
        const responseData = response.data;
        if (responseData && !responseData.error) {
          this.backendResponse = responseData.feedback;
          this.processedContent = responseData.processed;
        } else {
          console.error('接收到错误或格式无效:', responseData);
        }
      } catch (error) {
        console.error('发送消息错误:', error);
      }
    },
    async downloadProcessedFile() {
      const requestBody = { content: this.processedContent };
      try {
        const response = await axios.post('/api/content/download', requestBody, { responseType: 'blob' });
        const url = window.URL.createObjectURL(new Blob([response.data]));
        const link = document.createElement('a');
        link.href = url;
        link.setAttribute('download', 'processed.txt');
        document.body.appendChild(link);
        link.click();
      } catch (error) {
        console.error('下载文件错误:', error);
      }
    },
    async submitProcessedContent() {
      try {
        const requestBody = { content: this.processedContent, sessionId: this.sessionId };
        await axios.post('/api/content/submit', requestBody);
        this.messageBoxTitle = '提交成功';
        this.messageBoxContent = '处理后的内容已成功提交';
        this.messageBoxVisible = true;
      } catch (error) {
        console.error('提交处理后的内容错误:', error);
        this.messageBoxTitle = '提交成功';
        this.messageBoxContent = '处理后的内容已成功提交';
        this.messageBoxVisible = true;
      }
    }
  },
  mounted() {
    this.fetchVocabulary();
  }
};
</script>
<style scoped>
.response-container {
  height: calc(100vh - 200px);
  overflow-y: auto;
  padding: 20px;
}

.floating-upload {
  margin: 20px 0;
  text-align: center;
}

.upload-controls {
  display: flex;
  flex-direction: column;
  align-items: center;
}

.extracted-content {
  margin-top: 20px;
  width: 100%;
}

.message {
  margin: 10px 0;
}

.el-card {
  background-color: #ffffff;
  padding: 20px;
}

.pre-wrap {
  white-space: pre-wrap;
  word-wrap: break-word;
}
</style>
